package com.iwhalecloud.bss.kite.cucc.order.accept.constructor.inst;

import com.google.common.collect.Sets;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.common.util.SeqUtils;
import com.iwhalecloud.bss.kite.cucc.order.util.AcceptUtils;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstFunc;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstFuncExt;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.ProdInstFuncExtMapper;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstFunc;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataProdInst;
import com.ztesoft.bss.common.util.SpringUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

/**
 * 功能产品实例构造器
 * @version 1.0
 */
@Component
public class ProdInstFuncConstructor extends InstConstructor<KiteProdInstFunc, ProdInstFunc> {

    @Override
    public String getTableName() {
        return TableConsts.ProdInstFunc.getTableName();
    }

    @Override
    public InstType getParentInstType() {
        return InstType.PROD_INST;
    }

    @Override
    public ProdInstFunc build(OrderRequest orderRequest, String prodInstId, Map<String, Object> params) {
        if (Objects.isNull(orderRequest) || StringUtils.isBlank(prodInstId)) {
            return null;
        }

        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        KiteProdInstFunc kiteProdInstFunc = querySceneInstService.getProdInstFunc(orderRequest.getCustId(), prodInstId);
        KiteProdInst kiteProdInst = querySceneInstService.getProdInstByFuncProdInstId(orderRequest.getCustId(),
            prodInstId);
        if (isIneffectiveInst(kiteProdInstFunc) || isIneffectiveInst(kiteProdInst)) {
            return null;
        }

        kiteProdInstFunc.setAccProdInstId(kiteProdInst.getProdInstId());
        kiteProdInstFunc.setCompInstId(kiteProdInst.getOfferInstId());
        kiteProdInstFunc.setAccNum(kiteProdInst.getAccNum());
        kiteProdInstFunc.setUseCustId(kiteProdInst.getUseCustId());
        ProdInstFunc prodInstFunc = convert(orderRequest, kiteProdInstFunc, params);
        InstContainer.ofRequest(orderRequest).addProdInstFunc(prodInstFunc);

        ProdInst prodInst = buildParentInst(orderRequest, kiteProdInst.getProdInstId());
        if (AcceptUtils.isAddInst(prodInstFunc) && Objects.nonNull(prodInst)
            && StringUtils.isNotBlank(prodInst.getOwnerCustId())) {
            prodInstFunc.setOwnerCustId(prodInst.getOwnerCustId());
        }

        Map<String, ProdInstFuncExt> prodInstFuncExtMap = buildProdInstFuncExts(orderRequest, kiteProdInstFunc,
            prodInstFunc.getOwnerCustId());
        orderRequest.getInstContainer().getProdInstFuncExtMap().put(prodInstId, prodInstFuncExtMap);

        return prodInstFunc;
    }

    @Override
    public ProdInstFunc newInst(OrderRequest orderRequest, KiteProdInstFunc kiteProdInstFunc) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteProdInstFunc)) {
            return null;
        }

        Date now = new Date();
        ProdInstFunc prodInstFunc = KiteBeanUtils.transform(kiteProdInstFunc, ProdInstFunc.class, KiteInst.ACTION_TYPE);
        prodInstFunc.setOwnerCustId(orderRequest.getCustId());
        prodInstFunc.setActionType(ActionType.A.name());
        prodInstFunc.setProdIdOld(kiteProdInstFunc.getProdId());
        prodInstFunc.setProdTypeCd(KeyConsts.PROD_TYPE_CD_01);
        prodInstFunc.setCreateDate(now);
        prodInstFunc.setBeginRentDate(now);
        prodInstFunc.setLanId(orderRequest.getLanId());
        prodInstFunc.setRegionId(orderRequest.getRegionId());
        prodInstFunc.setStateCd(KeyConsts.STATE_ONWAY);
        prodInstFunc.setStatusDate(now);
        prodInstFunc.setCreateStaff(orderRequest.getStaffId());
        prodInstFunc.setOfferInstId(prodInstFunc.getCompInstId());
        prodInstFunc.setStatusCd(CoreDataProdInst.PRI_0002_130000);
        prodInstFunc.setCreateOrgId(orderRequest.getOrgId());
        prodInstFunc.setBusiModDate(now);
        if (StringUtils.isBlank(prodInstFunc.getUseCustId())) {
            prodInstFunc.setUseCustId(orderRequest.getCustId());
        }
        prodInstFunc.setLastOrderItemId("-1");
        prodInstFunc.setState(KeyConsts.STATE_ONWAY);
        prodInstFunc.setEffDate(now);
        prodInstFunc.setExpDate(AcceptUtils.getDefaultExpDate());
        prodInstFunc.setGrpProdNbr("-1");

        setAttrs(prodInstFunc, kiteProdInstFunc.getAttrMap(),
            Sets.newHashSet(StringUtils.upperCase(TableConsts.ProdInstFunc.getTableName())));

        return prodInstFunc;
    }

    /**
     * 构造功能产品实例属性
     * @param orderRequest
     * @param kiteProdInstFunc
     * @param custId
     * @return
     */
    public Map<String, ProdInstFuncExt> buildProdInstFuncExts(OrderRequest orderRequest,
        KiteProdInstFunc kiteProdInstFunc, String custId) {
        if (!ObjectUtils.allNotNull(orderRequest, kiteProdInstFunc)) {
            return new HashMap<>();
        }

        Map<String, ProdInstFuncExt> prodInstFuncExtMap = null;
        if (isAddByCurrent(orderRequest, kiteProdInstFunc)) {
            prodInstFuncExtMap = new HashMap<>();
            Set<Entry<String, KiteAttr>> entrySet = kiteProdInstFunc.getAttrMap().entrySet();
            for (Entry<String, KiteAttr> entry : entrySet) {
                KiteAttr attr = entry.getValue();
                if (!StringUtils.equalsIgnoreCase(TableConsts.ProdInstFuncExt.getTableName(), attr.getTableName())) {
                    continue;
                }

                ProdInstFuncExt prodInstFuncExt = toProdInstFuncExt(orderRequest, attr, kiteProdInstFunc, custId);
                if (Objects.nonNull(prodInstFuncExt)) {
                    prodInstFuncExtMap.put(prodInstFuncExt.getFieldName(), prodInstFuncExt);
                }
            }
        }
        else {
            prodInstFuncExtMap = getProdInstFuncExtMap(kiteProdInstFunc.getProdInstId(),
                kiteProdInstFunc.getOwnerCustId());
            if (Objects.equals(ActionType.D, kiteProdInstFunc.getActionType())) {
                prodInstFuncExtMap.forEach((fieldName, prodInstFuncExt) -> {
                    AcceptUtils.setActionType(prodInstFuncExt, ActionType.D.name());
                });
            }
            else {
                Date now = new Date();
                Map<String, KiteAttr> attrMap = kiteProdInstFunc.getAttrMap();
                String key = ManagerUtils.join(kiteProdInstFunc.getInstType(), kiteProdInstFunc.getInstId());
                List<KiteInstChange> instChanges = orderRequest.getInstChangeMap().getOrDefault(key, new ArrayList<>());
                for (KiteInstChange instChange : instChanges) {
                    if (!Objects.equals(ActionType.M, instChange.getActionType())) {
                        continue;
                    }

                    String fieldName = instChange.getFieldName();
                    String newValue = instChange.getNewValue();

                    KiteAttr attr = attrMap.get(fieldName);
                    if (Objects.isNull(attr) || !StringUtils
                        .equalsIgnoreCase(TableConsts.ProdInstFuncExt.getTableName(), attr.getTableName())) {
                        continue;
                    }

                    ProdInstFuncExt prodInstFuncExt = prodInstFuncExtMap.get(fieldName);
                    if (Objects.nonNull(prodInstFuncExt)) {
                        // 修改属性
                        if (!KiteStringUtils.equals(newValue, prodInstFuncExt.getAttrValue())) {
                            prodInstFuncExt.setAttrValue(newValue);
                            prodInstFuncExt.setUpdateStaff(orderRequest.getStaffId());
                            prodInstFuncExt.setUpdateDate(now);
                            AcceptUtils.setActionType(prodInstFuncExt, ActionType.M.name());
                        }
                    }
                    else {
                        // 新增属性
                        prodInstFuncExt = toProdInstFuncExt(orderRequest, attr, kiteProdInstFunc, custId);
                        if (Objects.nonNull(prodInstFuncExt)) {
                            prodInstFuncExtMap.put(prodInstFuncExt.getFieldName(), prodInstFuncExt);
                        }
                    }
                }
            }
        }

        return prodInstFuncExtMap;
    }

    /**
     * 把KiteAttr转换成ProdInstFuncExt
     * @param orderRequest
     * @param attr
     * @param kiteProdInstFunc
     * @param custId
     * @return
     */
    public ProdInstFuncExt toProdInstFuncExt(OrderRequest orderRequest, KiteAttr attr,
        KiteProdInstFunc kiteProdInstFunc, String custId) {
        if (!ObjectUtils.allNotNull(orderRequest, attr, kiteProdInstFunc)) {
            return null;
        }

        Date now = new Date();
        ProdInstFuncExt prodInstFuncExt = new ProdInstFuncExt();
        prodInstFuncExt.setProdInstFuncExtId(SeqUtils.getNext(TableConsts.ProdInstFuncExt));
        prodInstFuncExt.setOwnerCustId(custId);
        prodInstFuncExt.setActionType(ActionType.A.name());
        prodInstFuncExt.setProdInstId(kiteProdInstFunc.getProdInstId());
        prodInstFuncExt.setAttrId(attr.getAttrId());
        prodInstFuncExt.setAttrValue(attr.getValue());
        prodInstFuncExt.setFieldName(attr.getFieldName());
        prodInstFuncExt.setCompInstId(kiteProdInstFunc.getCompInstId());
        prodInstFuncExt.setStatusDate(now);
        prodInstFuncExt.setCreateStaff(orderRequest.getStaffId());
        prodInstFuncExt.setLanId(orderRequest.getLanId());
        prodInstFuncExt.setParProdInstAttrId("-1");
        prodInstFuncExt.setCreateDate(now);
        prodInstFuncExt.setBusiModDate(now);
        prodInstFuncExt.setEffDate(now);
        prodInstFuncExt.setExpDate(AcceptUtils.getDefaultExpDate());
        prodInstFuncExt.setStatusCd(CoreDataProdInst.PRI_0002_130000);

        return prodInstFuncExt;
    }

    /**
     * 根据功能产品实例id查询功能产品实例属性
     * @param prodInstId
     * @param custId
     * @return
     */
    public Map<String, ProdInstFuncExt> getProdInstFuncExtMap(String prodInstId, String custId) {
        if (StringUtils.isAnyBlank(prodInstId, custId)) {
            return new HashMap<>();
        }

        Example example = new Example(ProdInstFuncExt.class);
        example.createCriteria().andEqualTo("prodInstId", prodInstId).andEqualTo("ownerCustId", custId);
        ProdInstFuncExtMapper mapper = SpringUtil.getBean(ProdInstFuncExtMapper.class);
        List<ProdInstFuncExt> prodInstFuncExts = mapper.selectByExample(example);

        Map<String, ProdInstFuncExt> prodInstFuncExtMap = new HashMap<>();
        for (ProdInstFuncExt prodInstFuncExt : prodInstFuncExts) {
            if (Objects.equals(ActionType.A.name(), prodInstFuncExt.getActionType())) {
                prodInstFuncExt.setNewActionType(ActionType.K.name());
            }
            prodInstFuncExtMap.put(prodInstFuncExt.getFieldName(), prodInstFuncExt);
        }

        return prodInstFuncExtMap;
    }
}
